 /**********************
 * SINGLE USER LICENCE *
 *********************** 
 *	1. The MEDKit motor-control software is allowed to be downloaded to Emerge-Engineering MEDKit motor-control hardware only.
 *	2. The MEDKit motor-control software must not be used in any commercial projects, not even parts of the software. Requests for commercial licences are welcome.
 *	3. The MEDKit motor-control software must not be shared or disclosed with 3rd-party customers.
 *	4. The MEDKit motor-control software must not be used in any open-source project.
 * 
 * DISCLAIMER:  THE SOFTWARE IS FURNISHED
 * "AS IS" WITHOUT WARRANTY OF ANY KIND. EMERGE-ENGINEERING DISCLAIMS ALL OTHER WARRANTIES,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * NEITHER EMERGE-ENGINEERING NOR ITS AFFILIATES SHALL BE LIABLE FOR ANY DAMAGES ARISING
 * OUT OF THE USE OF OR INABILITY TO USE THE SOFTWARE, INCLUDING DAMAGES FOR
 * LOSS OF PROFITS, BUSINESS INTERRUPTION, OR ANY SPECIAL, INCIDENTAL, INDIRECT
 * OR CONSEQUENTIAL DAMAGES EVEN IF EMERGE-ENGINEERING HAS BEEN ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGES.
 *
 * Author:     Emerge-Engineering UG - www.emerge-engineering.de
 * Copyright:  Emerge-Engineering UG
 *             Stettiner Str. 6
 *             D-71701 Schwieberdingen
 *			   info@emerge-engineering.de
 * Date:	   2011/10/16
 ****************************************/

/* includes from Std Librarys */	
	#include "stm32f10x.h"
	#include "stm32f10x_tim.h" //for toggle LED function
	#include "stm32f10x_adc.h" //for ADC Trigger activation
	#include "stm32f10x_gpio.h" //for ADC Trigger activation
	#include "stm32f10x_dma.h" //for ADC dma interaction
	#include "MEDKit_HW_Init.h" // for hardware related functions
	#include "stm32f10x_dac.h" // for analog debug output of variables
	#include "stm32f10x_usart.h" //for USART

/* includes for TargetLink Code */
	#include "tl_basetypes.h"
	#include "MEDKit_IO.h"
	#include "MEDKit_Modul_Interfaces.h"
	#include "TRQ_Controller.h"
	#include "RPM_Controller.h"      
	#include "POS_Controller.h"
	#include "IHS.h"
	#include "LED_Block_Driver.h"
	#include "SVPWM.h"
	#include "Bus_Current_Filter.h"
	#include "State_Manager.h"

/* global variables */

	UInt16 BSW_M_Motor_Hall_Value_1; /* Digital Input from hall sensor 1 */
	UInt16 BSW_M_Motor_Hall_Value_2; /* Digital Input from hall sensor 2 */
	UInt16 BSW_M_Motor_Hall_Value_3; /* Digital Input from hall sensor 3 */

	UInt16 BSW_M_MC_FF1,BSW_M_MC_FF2; // Fault flags from MOSFET driver A4935

	UInt16 BSW_C_DAC_Channel_1_Select=1; /* used to switch between different signals that can be output on DAC (Pin A4)	*/
	UInt16 BSW_C_DAC_Channel_2_Select=1; /* used to switch between different signals that can be output on DAC (Pin A5)	*/
	
	UInt16 BSW_M_ADC_I_DC_BUS[2]; /* Stores two samples of bus-current (current from battery), measured two times during one PWM-cycle */
	UInt16 BSW_M_ADC_I_DC_BUS_Zero_Current_Voltage[2]; /* Stores two samples of the coresponding sensor offset */

	UInt16 BSW_M_ADC_Temp_MCU;
	Int32 BSW_M_Temp_MCU_Degree;

	UInt16 BSW_M_ADC_Channel_12; /* Free for your measurement */	
	UInt16 BSW_M_ADC_Channel_13; /* Free for your measurement */

	/* analog watchdog settings - don't change unless you know what you do */
	#define AWD_Treshold_Voltage_High 48 /* Inverter shuts down at this voltage */
	#define Calibration_Voltage 12 		 /* ADC calibration voltage */
	#define Sample_at_Calibration 12950	 /* ADC value at calibration voltage */
	#define AWD_Threshold_Sample_12Bit ((Sample_at_Calibration/Calibration_Voltage)*AWD_Treshold_Voltage_High)/16
	UInt16 BSW_C_ADC_AWD_HighThreshold_12Bit=AWD_Threshold_Sample_12Bit;
	UInt16 BSW_C_ADC_AWD_LowThreshold_12Bit=0;
	UInt16 BSW_M_ADC_AWD_Flag;

	UInt16 BSW_M_Dip_Switch_2;
	UInt16 BSW_M_Dip_Switch_3;
	UInt16 BSW_M_Dip_Switch_4;

/* External Symbols */
	extern UInt16 BSW_M_PWM_DMA_Buffer[4];	 /* to transfer duty-cycle setpoint to pwm-registers via DMA burst*/	
	extern UInt16 BSW_M_DMA_Buffer_ADC1[10]; /* to transfer ADC continuous converted samples from ADC */
	extern UInt16 A3945_Fault_Latch_Info[10];

/* Cyclic 0.1ms interrupt */
void TIM6_IRQHandler(void)
{
	BSW_M_ADC_AWD_Flag=ADC_GetFlagStatus(ADC1, ADC_FLAG_AWD); /* Check for analog watchdog */
	if (BSW_M_ADC_AWD_Flag) 
	{
		/* safe state on over voltage */
		TIM_CtrlPWMOutputs(TIM1, DISABLE);  /* active Low-Side MOSFETs --> short curcuit braking */
		//GPIOB->BRR = GPIO_Pin_1;			/* unncomment this line for free wheeling (floating motor phases) */
	}


	/**********************************************/
	/* Evaluate Hall Sensors (internal            */
	/**********************************************/
		
		BSW_M_Motor_Hall_Value_1 = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14);  /* Readout of the motor-internal hall-sensors with IO ports */   
		BSW_M_Motor_Hall_Value_2 = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13);  /* Readout of the motor-internal hall-sensors with IO ports */ 
		BSW_M_Motor_Hall_Value_3 = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_12);  /* Readout of the motor-internal hall-sensors with IO ports */ 
		MEDKit_IO_Hall_Sensor_Value = (BSW_M_Motor_Hall_Value_1 ) + ((BSW_M_Motor_Hall_Value_2) << 1) + ((BSW_M_Motor_Hall_Value_3) << 2);						/* feed internal-hall-sensor-evaluation function */ 
		
		IHS();																		/* call internal-hall-sensor-evaluation function (TargetLink Code) */

	/************************************************/
	/* Calculate duty-cycles for inverter actuation */
	/************************************************/  
	    
		SVPWM();	/* call SVPWM function (TargetLink Code */
	    
		TIM_ITConfig(TIM1, TIM_IT_Update, DISABLE); // Disable update interrupt
		BSW_M_PWM_DMA_Buffer[2]=MEDKit_IO_DutyCycle_Phase_C/33;		/* Sets the duty cycle for one phase of the three center alligned phases - This does not set the new values active - See TIM1 Update Interrupt*/
		BSW_M_PWM_DMA_Buffer[1]=MEDKit_IO_DutyCycle_Phase_B/33;		/* Sets the duty cycle for one phase of the three center alligned phases - This does not set the new values active - See TIM1 Update Interrupt*/
		BSW_M_PWM_DMA_Buffer[0]=MEDKit_IO_DutyCycle_Phase_A/33;		/* Sets the duty cycle for one phase of the three center alligned phases - This does not set the new values active - See TIM1 Update Interrupt*/
		TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE); // Enable update interrupt
		  

	/************************************************/
	/* Calculate Intermediate Bus Current */
	/************************************************/ 

		MEDKit_IO_U_Shunt_DC_BUS		= BSW_M_ADC_I_DC_BUS[1]<<1;  						/* current measured at the second falling PWM Edge */
		MEDKit_IO_U_Shunt_DC_BUS_Offset = BSW_M_ADC_I_DC_BUS_Zero_Current_Voltage[1]<<1; 	/* zero offset from current sensor */
  		
		Bus_Current_Filter();														/* call function (TargetLink Code) */

	/************************************************/
	/* Select 100us measurement variables to be sent to DAC1 (Pin A4) and DAC2 (Pin A5) */
	/************************************************/ 
		

		switch (BSW_C_DAC_Channel_1_Select)
		{
			case 1:  DAC_SetChannel1Data(DAC_Align_12b_L, ((Int16)BCF_OUT_Current_Amps*10)+32767); break;
			case 2:  DAC_SetChannel1Data(DAC_Align_12b_L, 0); break;
			case 3:  DAC_SetChannel1Data(DAC_Align_12b_L, 0); break;
			case 4:  DAC_SetChannel1Data(DAC_Align_12b_L, 0); break;
			case 5:  DAC_SetChannel1Data(DAC_Align_12b_L, 0); break;
			case 6:  DAC_SetChannel1Data(DAC_Align_12b_L, 0); break;
			case 7:  DAC_SetChannel1Data(DAC_Align_12b_L, 0); break;
			case 8:  DAC_SetChannel1Data(DAC_Align_12b_L, 0); break;
		   	case 9:  DAC_SetChannel1Data(DAC_Align_12b_L, 0); break;
			case 10: DAC_SetChannel1Data(DAC_Align_12b_L, ((Int16)BCF_OUT_Current_Amps*10)+32767); break;			
			default: break;
		}
		switch (BSW_C_DAC_Channel_2_Select)
		{
 			case 1:  DAC_SetChannel2Data(DAC_Align_12b_L, ((Int16)BCF_OUT_Current_Amps*10)+32767); break;
			case 2:  DAC_SetChannel2Data(DAC_Align_12b_L, 0); break;
			case 3:  DAC_SetChannel2Data(DAC_Align_12b_L, 0); break;
			case 4:  DAC_SetChannel2Data(DAC_Align_12b_L, 0); break;
			case 5:  DAC_SetChannel2Data(DAC_Align_12b_L, 0); break;
			case 6:  DAC_SetChannel2Data(DAC_Align_12b_L, 0); break;
			case 7:  DAC_SetChannel2Data(DAC_Align_12b_L, 0); break;
			case 8:  DAC_SetChannel2Data(DAC_Align_12b_L, 0); break;
			case 9:  DAC_SetChannel2Data(DAC_Align_12b_L, 0); break;
			case 10: DAC_SetChannel2Data(DAC_Align_12b_L, ((Int16)BCF_OUT_Current_Amps*10)+32767); break;
			default: break;
		}


	TIM_ClearITPendingBit(TIM6,TIM_IT_Update);
}


/* Cyclic 1ms interrupt */
void TIM5_IRQHandler(void)
{
		
	/**********************************************/
	/* Call torque-controler             		  */
	/**********************************************/
	TRQ_Controller();	/* call torque controller function (TargetLink Code) */		
	
   	TIM_ClearITPendingBit(TIM5,TIM_IT_Update);
}										 


/* Cyclic 10ms interrupt */
void TIM4_IRQHandler(void)
{
	TIM_ClearITPendingBit(TIM4,TIM_IT_Update);					/* Clear Interrupt Flag */
	
	/**********************************************/
	/* Call RPM-controller               		  */
	/**********************************************/
	RPM_Controller(); /* call RPM controller function (TargetLink Code) */

	/**********************************************/
	/* Start Single Scan Conversion               */
	/**********************************************/
		
		/*******************************
		ADC scan converted channels
		********************************/
		MEDKit_IO_ADC_Poti_Onboard  = BSW_M_DMA_Buffer_ADC1[0];
		BSW_M_ADC_Temp_MCU			= BSW_M_DMA_Buffer_ADC1[1];
		MEDKit_IO_ADC_U_Bus			= BSW_M_DMA_Buffer_ADC1[2];
		MEDKit_IO_ADC_TEMP_FET		= BSW_M_DMA_Buffer_ADC1[3];
		MEDKit_IO_eBike_Throttle	= BSW_M_DMA_Buffer_ADC1[4];	// ADC Channel 11
		BSW_M_ADC_Channel_12		= BSW_M_DMA_Buffer_ADC1[5];
		BSW_M_ADC_Channel_13		= BSW_M_DMA_Buffer_ADC1[6];


	TIM_ClearITPendingBit(TIM4,TIM_IT_Update);		/* Clear Interrupt Flag */

}




UInt16 BSW_C_S_Read_A3945=0;
/* Cyclic 100ms interrupt */
void TIM3_IRQHandler(void)
{
    /**********************************************/
	/* Feed and call position-controller          */
	/**********************************************/
	POS_Controller();											    /* call POS controller function (TargetLink Code) */

	/**********************************************/
	/* Get the state of buttons and switches      */
	/**********************************************/
	MEDKit_IO_PushButton_1     = (GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_8)>0);	/* Read out the state of the button digital input */
	MEDKit_IO_PushButton_2	   = (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_15)>0);	/* Read out the state of the button digital input */
	MEDKit_IO_PushButton_3	   = (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_13)>0);	/* Read out the state of the button digital input */
	BSW_M_Dip_Switch_2 = (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_2)>0);	/* Read out the state of the switch digital input */
	BSW_M_Dip_Switch_3 = (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_3)>0);	/* Read out the state of the switch digital input */
	BSW_M_Dip_Switch_4 = (GPIO_ReadInputDataBit(GPIOD,GPIO_Pin_4)>0);	/* Read out the state of the switch digital input */

	/**********************************************/
	/*  Read out error message of A4935		      */
	/**********************************************/
		if (BSW_C_S_Read_A3945) 
		{
			Read_A3945_Fault_Latch();
			BSW_C_S_Read_A3945=0;
		}
                    
	/**********************************************/
	/* Feed and call State-Machine                */
	/**********************************************/
	State_Manager();

	/*************************************************/
	/* Disable the MOSFET driver in case of an error */
	/*************************************************/
	if (MEDKit_IO_Inverter_Shutdown || BSW_M_ADC_AWD_Flag)		/* Statemanager can coast the inverter in case of error */
	{
		GPIOB->BRR = GPIO_Pin_1;	/* set COASTn low */
		GPIOB->BRR = GPIO_Pin_11;	/* set RESETn low */
	}
	else
	{ 
		GPIOB->BSRR = GPIO_Pin_1;	/* set COASTn high */ 
		GPIOB->BSRR = GPIO_Pin_11;	/* set RESETn low */
	}


	/**********************************************/
	/* Feed and call LED-gauge                    */
	/**********************************************/
	LED_Block_Driver();	/* call the LED-Block driver implemented as a TargetLink function */
		
	if (MEDKit_IO_LED_PORT & 0x80) GPIOB->BSRR = GPIO_Pin_6; else GPIOB->BRR = GPIO_Pin_6;	/* Choose which LED to light up */
	if (MEDKit_IO_LED_PORT & 0x40) GPIOB->BSRR = GPIO_Pin_7; else GPIOB->BRR = GPIO_Pin_7;	/* Choose which LED to light up */
	if (MEDKit_IO_LED_PORT & 0x20) GPIOB->BSRR = GPIO_Pin_8; else GPIOB->BRR = GPIO_Pin_8;	/* Choose which LED to light up */
	if (MEDKit_IO_LED_PORT & 0x10) GPIOB->BSRR = GPIO_Pin_9; else GPIOB->BRR = GPIO_Pin_9;	/* Choose which LED to light up */
	if (MEDKit_IO_LED_PORT & 0x08) GPIOE->BSRR = GPIO_Pin_1; else GPIOE->BRR = GPIO_Pin_1;	/* Choose which LED to light up */
	if (MEDKit_IO_LED_PORT & 0x04) GPIOE->BSRR = GPIO_Pin_2; else GPIOE->BRR = GPIO_Pin_2;	/* Choose which LED to light up */
	if (MEDKit_IO_LED_PORT & 0x02) GPIOE->BSRR = GPIO_Pin_3; else GPIOE->BRR = GPIO_Pin_3;	/* Choose which LED to light up */
	if (MEDKit_IO_LED_PORT & 0x01) GPIOE->BSRR = GPIO_Pin_4; else GPIOE->BRR = GPIO_Pin_4;	/* Choose which LED to light up */

	BT_send_continuous();

	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);							/* Clear the interrupt flag */
}



/* Cyclic 1000ms interrupt */
void TIM2_IRQHandler(void)
{
	/* Read out MC fault flags */
	BSW_M_MC_FF1=GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_15);
	BSW_M_MC_FF2=GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_14);
    
	/* Calculate MCU Temperature */
	MEDKit_IO_TEMP_MCU_Degree = (28399 - BSW_M_ADC_Temp_MCU) / 85 + 25;

	TIM_ClearITPendingBit(TIM2,TIM_IT_Update);		/* Clear the flag at the end, otherwise this process could be interrupted by other interrupts with the same priotiy */
}



UInt16 BSW_M_Number_Of_CC_Interrupts=0; /* Used to count the number of Capture Compare Interrupts */
/* Timer 1 (PWM_Timer) Update Interrupt */
/* This Interrupt is called once every PWM-period see TIM1 Setup of the repitition counter */
/* With the Interrupt you just have to re-enable the current measurement */
/* The duty-cycle values are transfered to the TIM1 config register by a DMA burst-write access */
void TIM1_UP_IRQHandler(void)
{
	BSW_M_Number_Of_CC_Interrupts=0;  /* Reset the CC counter, this enables the measurement of shunt volatages for the new PWM period */
	ADC_SoftwareStartInjectedConvCmd(ADC1,ENABLE); 
	ADC_SoftwareStartInjectedConvCmd(ADC2,ENABLE); 
	TIM_ITConfig(TIM1, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3, ENABLE);									/* enable CC1 .. C3 */
	TIM_ClearFlag(TIM1, TIM_FLAG_Update |TIM_FLAG_CC1 | TIM_FLAG_CC2 | TIM_FLAG_CC3 | TIM_FLAG_CC4);	/* clear all flags, not to have an interrupt shortly after enabling them */

}



/* PWM-Timer Capture Compare Interrupt */
/* This interupt is enabled at the beginning of each PWM period */
/* From the basics of single shunt measurement method you know, that you have to measure a shunt voltage twice within one PWMM period */
/* The first measurement has to start after the first fallig edge of the center aligned PWM */
/* The seccond measurement has to start after the second falling edge */
/* Because this interrupt is generated at any falling edge after the PWM period update, you automatically catch the two need measurements */
/* After the two measurements, this interrupt is disabled until the next PWM-period start with the TIM1 Update Interrupt */
UInt16 BSW_C_Trigger_Delay=2; /* Used to shift the start of injection measurement to about 2.95us after CC event, this is when current flows continuously */
UInt16 BSW_C_Delay_Cntr;
void TIM1_CC_IRQHandler(void)
{
	
	if ((TIM_GetITStatus(TIM1, TIM_IT_CC4) == SET))	
	{
		/* do not react on CC4 Interrupt if it happens by fault. */
	}
	else
	{
		//GPIOB->BSRR = GPIO_Pin_6;	 /*visualize current measurement trigger */		
		BSW_M_Number_Of_CC_Interrupts=BSW_M_Number_Of_CC_Interrupts+1;
		switch(BSW_M_Number_Of_CC_Interrupts)
		{
		case 1:
			for (BSW_C_Delay_Cntr=0;BSW_C_Delay_Cntr<BSW_C_Trigger_Delay;BSW_C_Delay_Cntr++){;} /* This is to compensate the deadtime, and the time until the phase current flows steadily */
			ADC_SoftwareStartInjectedConvCmd(ADC1,ENABLE); 
			ADC_SoftwareStartInjectedConvCmd(ADC2,ENABLE); 
			break;
		case 2:
			for (BSW_C_Delay_Cntr=0;BSW_C_Delay_Cntr<BSW_C_Trigger_Delay;BSW_C_Delay_Cntr++){;} /* This is to compensate the deadtime, and the time until the phase current flows steadily */
			ADC_SoftwareStartInjectedConvCmd(ADC1,ENABLE); 
			ADC_SoftwareStartInjectedConvCmd(ADC2,ENABLE); 
			TIM_ITConfig(TIM1, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3, DISABLE); /* Disable this Interrupt after two measured voltages */
			break;
		default: 
			/* nothing */		
			break;
		}					   
	}
	TIM_ClearFlag(TIM1, TIM_FLAG_CC1 | TIM_FLAG_CC2 | TIM_FLAG_CC3 | TIM_FLAG_CC4); /* clear any flag that may be set */ 
	//GPIOB->BRR = GPIO_Pin_6;  /*visualize current measurement trigger */		
}




/* ADC - Interupt Handler Function */
/* This function is called, after two triggered and converted shunt-voltage measurements */
/* This happens once during every PWM period */
Int16 Phase_A_Offset=32175;
Int16 Phase_C_Offset=32417;
Int16 BSW_M_I_Phase_A;
Int16 BSW_M_I_Phase_C;

void ADC_IRQHandler(void)
{
	if ((ADC_GetITStatus(ADC1, ADC_IT_JEOC) == SET))	/* End of Injected Channel Conversion Sequence */
	{
			BSW_M_I_Phase_A	 					= ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1);		/* Copy measured Phase Voltage A - Phase voltage Sensors may not be installed*/
			BSW_M_I_Phase_A=(Int16)((BSW_M_I_Phase_A<<1)-Phase_A_Offset);
			
			BSW_M_ADC_I_DC_BUS[0] 						= ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2);		/* Copy measured current sensor voltage behind first falling PWM Edge*/
			BSW_M_ADC_I_DC_BUS[1] 						= ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_3);		/* Copy measured current sensor voltage behind 2nd falling PWM Edge*/

			BSW_M_I_Phase_C								= ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_1);		/* Copy measured Phase Voltage C - Phase voltage Sensors may not be installed*/
			BSW_M_I_Phase_C								=(Int16)((BSW_M_I_Phase_C<<1)-Phase_C_Offset);
			
			BSW_M_ADC_I_DC_BUS_Zero_Current_Voltage[0]	= ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_2);		/* Copy measured zero current sensor voltage behind first falling PWM Edge*/
			BSW_M_ADC_I_DC_BUS_Zero_Current_Voltage[1]	= ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_3);		/* Copy measured zeno current sensor voltage behind 2nd falling PWM Edge*/
			
			ADC_ClearFlag(ADC1, ADC_FLAG_JEOC);			/* Clear Interrupt Flag */
			ADC_ClearFlag(ADC2, ADC_FLAG_JEOC);			/* Clear Interrupt Flag */
	}
}
